﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InfFront.UICore
{
    /// <summary>
    /// Generic IContainer implementation
    /// </summary>
    [Serializable]
    public class Container<ItemType> : IContainer<ItemType>
    {
        private List<ItemType> origin;

        public Container()
        {
            origin = new List<ItemType>();
        }

        public void Add(ItemType item)
        {
            origin.Add(item);
        }

        public bool Remove(ItemType item)
        {
            return origin.Remove(item);
        }

        public virtual void Clear()
        {
            origin.Clear();
        }

        #region IContainer<ItemType> Members

        public int GetCount()
        {
            return origin.Count; 
        }

        public ItemType GetItem(int index)
        {
            return origin[index];
        }

        #endregion

        #region IEnumerable<ItemType> Members

        public IEnumerator<ItemType> GetEnumerator()
        {
            return origin.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return origin.GetEnumerator();
        }

        #endregion
    }

    /// <summary>
    /// IContainer extension members
    /// </summary>
    public static class IContainerExtensions
    {
        /// <summary>
        /// Checks whether the *value* is in the *container*
        /// </summary>
        /// <typeparam name="ItemType">Container item type</typeparam>
        /// <param name="container">the container to search in</param>
        /// <param name="value">the value to search for</param>
        /// <returns></returns>
        public static bool Contains<ItemType>(this IContainer<ItemType> container, ItemType value)
        {
            foreach (ItemType item in container)
            {
                if (value.Equals(item))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Retrieves all the elements that match the conditions defined by the specified predicate.
        /// </summary>
        /// <param name="match">The System.Predicate<ItemType> delegate that defines the conditions of the elements to search for</param>
        /// <returns>
        /// An IContainer<ItemType> instance containing all the elements that match 
        /// the conditions defined by the specified predicate, if found; 
        /// otherwise, an empty IContainer<ItemType> instance.
        /// </returns>
        public static IContainer<ItemType> FindAll<ItemType>(this IContainer<ItemType> container, Predicate<ItemType> match)
        {
            return container.FindAndCastAll<ItemType, ItemType>(match);
        }

        /// <summary>
        /// Retrieves all the elements that match the conditions defined by the specified predicate and casts it to the type specified
        /// </summary>
        /// <param name="match">The System.Predicate<ItemType> delegate that defines the conditions of the elements to search for</param>
        /// <returns>
        /// An IContainer<ItemType> instance containing all the elements that match 
        /// the conditions defined by the specified predicate, if found; 
        /// otherwise, an empty IContainer<ItemType> instance.
        /// </returns>
        public static IContainer<DestType> FindAndCastAll<ItemType, DestType>(this IContainer<ItemType> container, Predicate<ItemType> match)
            where ItemType: DestType
        {
            var result = new Container<DestType>();
            foreach (ItemType item in container)
            {
                if (match(item))
                    result.Add(item);
            }
            return result;
        }
    }

    public class EnumerableObjects : IEnumerable<object>
    {
        System.Collections.IEnumerable oldIEnum;

        public EnumerableObjects(System.Collections.IEnumerable oldIEnum)
        {
            this.oldIEnum = oldIEnum;
        }

        private class ObjectEnumerator : IEnumerator<object>
        {
            System.Collections.IEnumerator oldIEnum;

            public ObjectEnumerator(System.Collections.IEnumerator oldIEnum)
            {
                this.oldIEnum = oldIEnum;
            }

            #region IEnumerator<object> Members

            public object Current
            {
                get { return oldIEnum.Current; }
            }

            #endregion

            #region IDisposable Members

            public void Dispose()
            {
                oldIEnum = null;
            }

            #endregion

            #region IEnumerator Members


            public bool MoveNext()
            {
                return oldIEnum.MoveNext();
            }

            public void Reset()
            {
                oldIEnum.Reset();
            }

            #endregion
        }

        #region IEnumerable<object> Members

        public IEnumerator<object> GetEnumerator()
        {
            return new ObjectEnumerator(oldIEnum.GetEnumerator());
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return oldIEnum.GetEnumerator();
        }

        #endregion
    }
}
